#include "Analizador_Sintactico.h"
#include "Constantes.h"
#include <ctype.h>

Analizador_Sintactico::Analizador_Sintactico() {
	Cargar_stopwords();
}

// Analizador de palabras para indexar, retorna la cantidad de terminos q se extrajeron
int Analizador_Sintactico::Analizador(const char* directorio, std::string nom_archivo, unsigned int nro_doc, std::fstream *arch_aux) {
	size_t pos_espacio = 0;
	std::string aux = directorio;
	std::string palabra, linea;
	bool indexar = false;
	int terminos = 0;
	aux += "/";
	aux += nom_archivo;
	std::ifstream archivo(aux.c_str());
	if((!archivo.is_open()) || (!archivo.good())) {
		//std::cerr << "El archivo no se abrio correctamente " << std::endl;
		return -1;
	}
	while(getline(archivo, linea, '\n')) {
		if(linea.size() > 1) {
			while(linea.size() != 0) {
				if((pos_espacio = linea.find_first_of(" ")) != std::string::npos) {
					indexar = true;
					palabra = linea.substr(0, pos_espacio);
					linea.erase(0, pos_espacio + 1);
					if((palabra.find(" ") != std::string::npos) || (palabra.size() == 0))
						indexar = false;
				}
				else {
					palabra = linea;
					linea.clear();
				}
				//palabras++;
				if(indexar) {
					// Antes de convertir palabra hay q cargar las stopwords al árbol y las busco de ahi
					Convertir_palabra(&palabra);
					if(palabra.size() > 0) {
						// Si la palabra no es un stop word se indexa
						if(!stopwords.buscarStopword(palabra)) {
							//std::cout << palabra << std::endl;
							palabra.push_back('\n');
							// Escribo el término en la estructura auxiliar
							(*arch_aux) << palabra;
							terminos++;
						}
					}
				}
			}
		}
	}
	return terminos;
}

void Analizador_Sintactico::Convertir_palabra(std::string *palabra) {
	char letra_sinpunteacion;
	int digitos_contiguos = 0;
	bool borro_caracter = false;
	bool borro_letra = false;
	for(size_t i = 0; i < (*palabra).size(); i++) {
		//std::cout << "Tam palabra: " << (*palabra).size() << std::endl;

		// Si empieza con signos, los elimino
		if(Es_simbolo((*palabra)[i], (*palabra)[i + 1]))
			borro_caracter = true;

		// Paso a minuscula
		if(Es_letra((*palabra)[i], (*palabra)[i + 1])) {
			if(Es_punteada((*palabra)[i])) {
				letra_sinpunteacion = Identificar_letrapunteada((*palabra)[i+1]);
				borro_caracter = true;
				borro_letra = true;
			}
			if(!Es_minuscula((*palabra)[i], (*palabra)[i+1]))
				(*palabra)[i] = tolower((*palabra)[i]);
			digitos_contiguos = 0;
		}

		// Solo las palabras q sean solo números serán reducidas
		if(Es_numero((*palabra)[i]))
			digitos_contiguos++;

		if(borro_caracter) {
			(*palabra).erase(i, 1);
			if(borro_letra) {
				(*palabra)[i] = letra_sinpunteacion;
				borro_letra = false;
			}
			i--;
			borro_caracter = false;
		}
	}

	// Si digitos_contiguos = tam_palabra => solo números (nada de letras)
	if((digitos_contiguos == (*palabra).size()) && (digitos_contiguos > 4)) {
		for(size_t i = 4; i < (*palabra).size(); i++) {
			(*palabra).erase(i, 1);
			i--;
			digitos_contiguos--;
		}
	}
}

// Carga las stopwords en memoria, estaría bueno q las meta en un árbol trie y realizar la busqueda de ahi
int Analizador_Sintactico::Cargar_stopwords() {
	size_t pos_espacio = 0;
	std::string palabra, linea;
	std::ifstream archivo(nom_arch_stopwords);
	if((!archivo.is_open()) || (!archivo.good())) {
		//std::cerr << "El archivo no se abrio correctamente " << std::endl;
		return -1;
	}
	while(getline(archivo, linea)) {
		//std::cout << "Linea: " << linea << std::endl;
		while(linea.size() != 0) {
			if((pos_espacio = linea.find_first_of(" ")) != std::string::npos) {
				//std::cout << "ENTRA1 " << pos_espacio << std::endl;
				palabra = linea.substr(0, pos_espacio);
				linea.erase(0, pos_espacio + 1);
			}
			else {
				//std::cout << "ENTRA2" << std::endl;
				palabra = linea;
				linea.clear();
			}
			//std::cout << "Palabra: " << palabra << std::endl;
			stopwords.insertarTermino(palabra, NULL, NULL);
		}
	}
	return 0;
}

void Analizador_Sintactico::verStopwords() {
	std::fstream archivos(stop, std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
	this->stopwords.recorrerArbol(&archivos);
}

bool Analizador_Sintactico::Es_minuscula(char letra, char puntuacion) {
	if(((letra >= 'a') && (letra <= 'z')) || (Es_punteada_minus(letra, puntuacion)))
		return true;
	return false;
}

bool Analizador_Sintactico::Es_mayuscula(char letra, char puntuacion) {
	if(((letra >= 'A') && (letra <= 'Z')) || (Es_punteada_mayus(letra, puntuacion)))
		return true;

	return false;
}

bool Analizador_Sintactico::Es_numero(char letra) {
	if((letra >= '0') && (letra <= '9'))
		return true;
	return false;
}

bool Analizador_Sintactico::Es_letra(char letra, char puntuacion) {
	if((Es_minuscula(letra, puntuacion)) || (Es_mayuscula(letra, puntuacion)))
		return true;
	return false;
}

bool Analizador_Sintactico::Es_simbolo(char letra, char puntuacion) {
	if((Es_letra(letra, puntuacion)) || (Es_numero(letra)))
		return false;
	return true;
}

//Identifica la letra punteada, y retorna la letra sin ningún signo de punteacion
char Analizador_Sintactico::Identificar_letrapunteada(char letra) {
	char letra_sinpunteacion;
	switch((unsigned char)letra) {
	case(129):
		//cout << "A" << endl;
		letra_sinpunteacion = 'A';
		break;
	case(137):
		//cout << 'E' << endl;
		letra_sinpunteacion = 'E';
		break;
	case(141):
		//cout << 'I' << endl;
		letra_sinpunteacion = 'I';
		break;
	case(145):
			//palabra[i-1] = 'N';
		letra_sinpunteacion = 'N';
		break;
	case(147):
		//cout << 'O' << endl;
		letra_sinpunteacion = 'O';
		break;
	case(154):
		//cout << 'U' << endl;
		letra_sinpunteacion = 'U';
		break;
	case(161):
		//cout << 'a' << endl;
		letra_sinpunteacion = 'a';
		break;
	case(169):
		//cout << 'e' << endl;
		letra_sinpunteacion = 'e';
		break;
	case(173):
		//cout << 'i' << endl;
		letra_sinpunteacion = 'i';
		break;
	case(177):
		//cout << 'n' << endl;
		letra_sinpunteacion = 'n';
		break;
	case(179):
		//cout << 'o' << endl;
		letra_sinpunteacion = 'o';
		break;
	case(186):
		//cout << 'u' << endl;
		letra_sinpunteacion = 'u';
		break;
	}
	return letra_sinpunteacion;
}

// Devuelve true si es punteada y le borra la punteación
bool Analizador_Sintactico::Es_punteada(char acento) {
	if((unsigned char)acento == 195)
		return true;
	return false;
}


// Letra en minuscula con acento, o con el moño de la "ñ"
bool Analizador_Sintactico::Es_punteada_minus(char letra, char puntuacion) {
	unsigned char aux = (unsigned char)puntuacion;
	if((unsigned char)letra == 195)
		if((aux == 161) || (aux == 169) || (aux == 173) ||
				(aux == 177) || (aux == 179) || (aux == 186))
			return true;
	return false;
}

// Letra en mayuscula con acento, o con el moño de la "Ñ"
bool Analizador_Sintactico::Es_punteada_mayus(char letra, char puntuacion) {
	unsigned char aux = (unsigned char)puntuacion;
	if((unsigned char)letra == 195) {
		if((aux == 129) || (aux == 137) || (aux == 141) ||
				(aux == 145) || (aux == 147) || (aux == 154)) {
			return true;
		}
	}
	return false;
}

Analizador_Sintactico::~Analizador_Sintactico() {}
